package xvideo

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"strings"

	"github.com/tidwall/gjson"

	"github.com/disintegration/imaging"
	ffmpeg "github.com/u2takey/ffmpeg-go"
)

// GetVideoFrameCount --  @#使用帧率＊时长获取视频总帧数
func GetVideoFrameCount(videoPath string) (uint64, error) {
	// 构建 ffprobe 命令
	cmd := exec.Command(
		"ffprobe",
		"-v", "error", // 设置日志级别为 error，只显示错误信息
		"-select_streams", "v:0", // 选择第一个视频流
		"-show_entries", "stream=r_frame_rate", // 指定要显示的信息是 stream 部分的 nb_frames (估计的总帧数)
		"-of", "default=noprint_wrappers=1:nokey=1", // 设置输出格式，只打印值
		videoPath, // 输入视频文件路径
	)

	// 执行命令并获取输出
	output, err := cmd.CombinedOutput()
	if err != nil {
		return 0, fmt.Errorf("执行 ffprobe 失败: %w, 输出: %s", err, string(output))
	}

	// 将输出的字符串转换为整数
	frameRateStr := strings.TrimSuffix(strings.TrimSpace(string(output)), "/1")
	frameRate, err := strconv.Atoi(frameRateStr)
	if err != nil {
		return 0, fmt.Errorf("解析帧数字符串失败: %w, 原始字符串: %s", err, frameRateStr)
	}

	cmd2 := exec.Command(
		"ffprobe",
		"-v", "error",
		"-show_entries", "format=duration",
		"-of", "default=noprint_wrappers=1:nokey=1",
		videoPath,
	)

	// 执行命令并获取输出
	output2, err := cmd2.CombinedOutput()
	if err != nil {
		return 0, fmt.Errorf("执行 ffprobe 失败: %w, 输出: %s", err, string(output2))
	}

	// 将输出的字符串转换为整数
	frameDurationStr := strings.TrimSpace(string(output2))
	frameDuration, err := strconv.ParseFloat(frameDurationStr, 64)
	if err != nil {
		return 0, fmt.Errorf("解析帧数字符串失败: %w, 原始字符串: %s", err, frameDurationStr)
	}
	return uint64(float64(frameRate) * frameDuration), nil
}

func ReadFrameAsJpeg(inFileName string, frameNum uint64, aid int, cid int, dir string) (string, error) {
	buf := bytes.NewBuffer(nil)
	err := ffmpeg.Input(inFileName).
		Filter("select", ffmpeg.Args{fmt.Sprintf("gte(n,%d)", frameNum)}).
		Output("pipe:", ffmpeg.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg"}).
		WithOutput(buf, os.Stdout).
		Run()
	if err != nil {
		panic(err)
	}
	img, err := imaging.Decode(buf)
	if err != nil {
		return "", err
	}
	imgCroped := imaging.CropCenter(img, img.Bounds().Dy(), 200)
	os.MkdirAll(dir+"/"+strconv.Itoa(aid)+"/"+strconv.Itoa(cid), os.ModePerm)
	path := fmt.Sprintf("%s/%d/%d/out_%d.jpeg", dir, aid, cid, frameNum)
	err = imaging.Save(imgCroped, path)
	if err != nil {
		return "", err
	}
	return path, nil
}

// GetHlsScreen --  @# 获取视频流视频的尺寸大小
func GetHlsScreen(input string) (width, height int64, err error) {
	vinfo, err := ffmpeg.Probe(input)
	if err != nil {
		return 0, 0, err
	}
	theWidth := gjson.Get(vinfo, "streams.0.width").Int()
	theHeight := gjson.Get(vinfo, "streams.0.height").Int()
	return theWidth, theHeight, nil
}
